package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.team.TeamUserHelp;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.AttrLenthConstant;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WorkOrderErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.listbatch.pojo.TeamBatchPojo;
import com.xbongbong.pro.team.TeamAfterVerifyDTO;
import com.xbongbong.pro.team.TeamVerifyDTO;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.enums.dictionary.WorkOrderShipStatusEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.help.SaasProductHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.util.ProductUtil;
import com.xbongbong.util.ValidateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleFromFormData;

/**
 * @author 吴峰
 * @date 2021/07/15 17:15
 */
@Service("workOrderAnalyticalServiceImpl")
public class WorkOrderValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {
    private static final Logger LOGGER = LoggerFactory.getLogger(WorkOrderValidateAnalyticalServiceImpl.class);

    @Resource
    private CommonHelp commonHelp;
    @Resource
    private SaasProductHelp saasProductHelp;
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private AnalyticalHelp analyticalHelp;
    @Resource
    private TeamUserHelp teamUserHelp;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.WORK_ORDER.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
        if (Objects.equals(validateDataDTO.getFromOuterLink(), 1)) {
            // 外链新建，因为没有负责人和协同人这两个，所以不需要校验
            return;
        }
        //没有负责人单协同人
        //工单极其特殊的协同人负责人防重复校验（自由流程工单负责人，指定流程第一阶段为指定为人员的情况）

        TeamVerifyDTO teamVerifyDTO = new TeamVerifyDTO();
        BeanUtil.copyProperties(validateDataDTO, teamVerifyDTO);
        boolean isNew = Objects.isNull(validateDataDTO.getDataId()) || Objects.equals(validateDataDTO.getDataId(), 0L);
        String creatorId = StringUtil.isNotEmpty(validateDataDTO.getCreatorId()) ? validateDataDTO.getCreatorId() : validateDataDTO.getUserId();
        teamVerifyDTO.setFromDetail(false);
        teamVerifyDTO.setIsNew(isNew);
        teamVerifyDTO.setDataId(Arrays.asList(validateDataDTO.getDataId()));
        teamVerifyDTO.setCreatorId(creatorId);
        teamVerifyDTO.setFromApproval(Objects.nonNull(validateDataDTO.getTaskId()));
        List<ReturnUserAndDepartmentPojo> ownerList = validateDataDTO.getOwnerIds();
        List<ReturnUserAndDepartmentPojo> coUserList = validateDataDTO.getCoUserId();
        List<String> ownerIdList = new ArrayList<>();
        List<String> coUserIdList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(ownerList)) {
            ownerList.forEach(owner -> ownerIdList.add(Objects.toString(owner.getId(), "")));
        }
        if (CollectionsUtil.isNotEmpty(coUserList)) {
            coUserList.forEach(coUser -> coUserIdList.add(Objects.toString(coUser.getId(), "")));
        }

        //根据是否传工单负责人来判断是否是自由流程还是指定流程
        boolean ifFree = false;
        JSONObject data = validateDataDTO.getData();
        if (Objects.nonNull(data.get(WorkOrderEnum.MANAGER_ID.getAttr()))) {
            ifFree = true;
        }
        //自由流程和指定流程的负责人和协同人防重复处理不同处理
        if (ifFree) {
            ownerIdList.add(data.get(WorkOrderEnum.MANAGER_ID.getAttr()).toString());
        }

        teamVerifyDTO.setNewAddMainUserList(new HashSet<>(ownerIdList));
        teamVerifyDTO.setNewAddCoUserList(new HashSet<>(coUserIdList));
        TeamAfterVerifyDTO teamAfterVerifyDTO = teamUserHelp.verifyFromForm(teamVerifyDTO);
        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = validateDataDTO.getSaasNeedRedundantAttrPoJo() == null ?
                new SaasNeedRedundantAttrPojo() : validateDataDTO.getSaasNeedRedundantAttrPoJo();
        saasNeedRedundantAttrPojo.setTeamAfterVerifyDTO(teamAfterVerifyDTO);
        List<TeamBatchPojo> teamBatchPojos = teamAfterVerifyDTO.getTeamBatchPojos();
        if (CollectionsUtil.isNotEmpty(teamBatchPojos)) {
            throw new XbbException(teamBatchPojos.get(0).getCode(), teamBatchPojos.get(0).getFailMsgReason());
        }

    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
       try {
           JSONObject data = validateDataDTO.getData();
           String corpid = validateDataDTO.getCorpid();
           Long dataId = validateDataDTO.getDataId();
           boolean isNew = analyticalHelp.isNew(validateDataDTO.getDataId(), validateDataDTO.getTaskId(), validateDataDTO.getCorpid());

           Map<String, FieldAttrEntity> explainMap = validateDataDTO.getExplainMap();

           //校验编号长度且编号存在
           FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
           FieldAttrEntity sheetNo = explainMap.getOrDefault(WorkOrderEnum.SHEET_NO.getAttr(), fieldAttrEntity);
           FieldAttrEntity memoField = explainMap.getOrDefault(WorkOrderEnum.MEMO.getAttr(), fieldAttrEntity);
           //编号校验
           if (Objects.nonNull(sheetNo) && Objects.equals(sheetNo.getStrictController(), BasicConstant.ZERO)) {
               ValidateUtil.checkSerialNumber(validateDataDTO.getSerialNo(), Objects.toString(sheetNo.getAttrName(), ""));
           }
           //格式化关联客户，联系人，机会，合同
           SaveFormatHelp.formatLinkBusiness4Save(data, WorkOrderEnum.LINK_CUSTOMER.getAttr(), WorkOrderEnum.LINK_CUSTOMER_HIDE.getAttr(), WorkOrderEnum.LINK_CUSTOMER.getFieldType());
           SaveFormatHelp.formatLinkBusiness4Save(data, WorkOrderEnum.LINK_CONTACT.getAttr(), WorkOrderEnum.LINK_CONTACT_HIDE.getAttr(), WorkOrderEnum.LINK_CONTACT.getFieldType());
           SaveFormatHelp.formatLinkBusiness4Save(data, WorkOrderEnum.LINK_OPPORTUNITY.getAttr(), WorkOrderEnum.LINK_OPPORTUNITY_HIDE.getAttr(), WorkOrderEnum.LINK_OPPORTUNITY.getFieldType());
           SaveFormatHelp.formatLinkBusiness4Save(data, WorkOrderEnum.LINK_CONTRACT.getAttr(), WorkOrderEnum.LINK_CONTRACT_HIDE.getAttr(), WorkOrderEnum.LINK_CONTRACT.getFieldType());
           //TODO 联系方式校验  该校验还没做

           //实施备件（产品）校验
           //获取工单相应的出库单内的产品信息，进行校验
           Boolean productCanSee = true;
           if (!isNew) {
               productCanSee = commonHelp.attrCanSee(validateDataDTO.getExplainMap().get(WorkOrderEnum.SPARE_PARTS.getAttr()),validateDataDTO.getDataId(),validateDataDTO.getCreatorId(),validateDataDTO.getLoginUser(),validateDataDTO.getCorpid(),XbbRefTypeEnum.WORK_ORDER.getCode());
           }
           JSONArray sparePartsArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,WorkOrderEnum.SPARE_PARTS.getAttr(),new JSONArray());
           if (isNew || productCanSee) {
               Integer shipStatus = validateProduct(sparePartsArray, corpid, isNew, dataId);
               data.put(WorkOrderEnum.SHIP_STATUS.getAttr(), shipStatus);
           }

           //地址
           //服务价格
           Double servicePrice = getDoubleFromFormData(data, WorkOrderEnum.SERVICE_PRICE.getAttr());
           if (servicePrice != null && servicePrice < 0) {
               throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222059);
           }
           //实施时间
           //工单备注 校验长度
           ValidateUtil.checkFieldEntityLength(data, WorkOrderEnum.MEMO.getAttr(), Objects.toString(memoField.getAttrName(), ""), AttrLenthConstant.MEMO_MAX_LENGTH);
           //紧急程度
           Map<String,Boolean> attrCanSeeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
           attrCanSeeMap.put(WorkOrderEnum.SPARE_PARTS.getAttr(),productCanSee);
           SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = new SaasNeedRedundantAttrPojo();
           saasNeedRedundantAttrPojo.setAttrCanSeeMap(attrCanSeeMap);
           validateDataDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPojo);
       } catch (XbbException e) {
           throw e;
       } catch (Exception e) {
           LOGGER.error("WorkReportValidateAnalyticalServiceImpl.beforeSave error", e);
           throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
       }
    }



    private Integer validateProduct(JSONArray jsonArray, String corpid, boolean isNew,Long dataId) throws XbbException {
        Set<Long> pageProductIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Integer shipStatus = WorkOrderShipStatusEnum.EMPTY.getCode();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
        }
        Map<String,Double> productNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        Map<Long,String> pageProductMap = saasProductHelp.productExit(corpid,new ArrayList<>(pageProductIds));
        // 新建有关联产品，改出库状态
        if (isNew && !Objects.equals(pageProductMap.size(), 0)) {
            shipStatus = WorkOrderShipStatusEnum.UNSHIPPED.getCode();
        }
        if (!isNew){
            Map<String,Double> businessProductMap = saasProductHelp.getOutstockProduct(corpid,dataId, OutstockTypeEnum.WORK_ORDER_OUTSTOCK.getCode(), pageProductMap);
            businessProductMap.remove(BusinessConstant.HAS_APPROVAL_DATA);
            boolean haveCorresponding = false;
            for (String s : businessProductMap.keySet()) {
                if (s.contains("_")) {
                    haveCorresponding = true;
                    break;
                }
            }
            boolean needMerge = !businessProductMap.isEmpty() && !haveCorresponding;
            for (Object object:jsonArray) {
                JSONObject jsonObject = (JSONObject) object;
                Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
                Long productSubId = jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
                String key;
                if (needMerge) {
                    key = productId.toString();
                } else {
                    key = productId + "_" + productSubId;
//                    if (Objects.nonNull(productSubId)) {
//                        key = productId + "_" + productSubId;
//                    } else {
//                        continue;
//                    }
                }
                Double productNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
                Double num = productNumMap.getOrDefault(key,0D);
                num += productNum;
                productNumMap.put(key,num);
            }
            // 修改出库状态
            shipStatus = choseShippedStatus(productNumMap, businessProductMap);

            ProductUtil.upstreamDocumentsProductNumLegalCheck(false,businessProductMap,productNumMap,pageProductMap, I18nMessageUtil.getMessage(I18nStringConstant.LESS_WORK_ORDER_NUM));
        }
        return shipStatus;
    }
    /**
     * 变更出库状态
     * @param productNumMap 工单产品数量
     * @param businessProductMap 已出库产品数量
     * @return java.lang.Integer
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2020/12/23 17:18
     * @version 1.0
     */
    private Integer choseShippedStatus(Map<String, Double> productNumMap, Map<String, Double> businessProductMap) {
        Integer shipStatus = WorkOrderShipStatusEnum.EMPTY.getCode();
        boolean shippedFlag = false;
        boolean unShippedFlag = false;
        int flag;
        for (Map.Entry<String, Double> entry : productNumMap.entrySet()) {
            String k = entry.getKey();
            Double v = entry.getValue();
            if (businessProductMap.containsKey(k)) {
                flag = Arith.compare(businessProductMap.get(k),v);
                if (flag == 0) { // 全部出库
                    shipStatus = WorkOrderShipStatusEnum.SHIPPED.getCode();
                    shippedFlag = true;
                }
                if (flag < 0) { // 部分出库
                    shipStatus = WorkOrderShipStatusEnum.DELIVERED.getCode();
                    break;
                }
                continue;
            }
            // 出库数量没有就是未出库
            shipStatus = WorkOrderShipStatusEnum.UNSHIPPED.getCode();
            unShippedFlag = true;
        }
        // 以下情况修改出库状态为部分出库
        if (shippedFlag && unShippedFlag) {
            shipStatus = WorkOrderShipStatusEnum.DELIVERED.getCode();
        }
        return shipStatus;
    }
    
}
